#pragma once
#include <string>
#include <unordered_map>
#include <pthread.h>
#include "LockGuard.hpp"
#include "Code.hpp"
#include "Log.hpp"
namespace wyl
{
#define MAX_NUM 5


    class User
    {
    public:
        User(const std::string &url, int count) : _url(url), _count(count) {}
        User() {}

        void SetUrl(const std::string &url) { _url = url; }
        void SetCount(int count) { _count = count; }
        std::string GetUrl() const { return _url; }
        int GetCount() const { return _count; }
        void SetCode(const std::string &code) { _code = code; }
        std::string GetCode() { return _code; }
        

        void Execone() { _count--; } // 执行一次
    private:
        std::string _url;
        int _count;
        std::string _code;
    };

    class UserManager
    {
    private:
        UserManager() : _num(0)
        {
            pthread_mutex_init(&_mtx, nullptr);
            _users = new std::unordered_map<std::string, User>();
            _cm = new CodeManager();

            bool ret = _cm->ReadCodes();
            if(!ret)logMessage(FATAL,"code file read failed"); 

        }
        ~UserManager()
        {
            if(_users) delete _users;
            if(_cm) delete _cm;
            pthread_mutex_destroy(&_mtx);
        }
        UserManager(const UserManager& us);
        UserManager operator=(const UserManager& us);
    public:

        void begin(const User &user)
        {
            LockGuard lock(&_mtx);
            _users->insert(std::make_pair(user.GetUrl(), user));
            _num++;
        }

        void over(const std::string &url)
        {
            LockGuard lock(&_mtx);
            auto it = _users->find(url);
            if (it == _users->end())
                return;
            _users->erase(it);
            _num--;
            logMessage(NORMAL,"%s over ....",url.c_str());
        }

        bool isexist(const std::string &url)
        {
            LockGuard lock(&_mtx);
            auto it = _users->find(url);
            if (it == _users->end())
                return false;
            return true;
        }

        bool IsFull() { return _num >= MAX_NUM; }

        static UserManager* GetInstance()
        {
            static pthread_mutex_t _static_mtx = PTHREAD_MUTEX_INITIALIZER;
            if(_instance == nullptr)
            {
                LockGuard lock(&_static_mtx);
                if(_instance == nullptr)
                {
                    _instance = new UserManager();
                }
            }
            return _instance;
        }

        CodeManager* GetCodes() {if(this == nullptr) logMessage(DEBUG,"this is nullptr");  return _cm;}

    private:
        std::unordered_map<std::string, User> *_users; // 用户管理
        CodeManager *_cm;                              // code管理
        pthread_mutex_t _mtx;
        int _num; // 用户数量
        static UserManager* _instance; 
        
    };
    UserManager* UserManager::_instance = nullptr;
}
